package com.erlang4j.internal;

import static com.erlang4j.api.Erlang4jMessageLanguage.atom;
import static com.erlang4j.api.Erlang4jMessageLanguage.binding;
import static com.erlang4j.api.Erlang4jMessageLanguage.makeArray;
import static com.erlang4j.api.Erlang4jMessageLanguage.string;
import static com.erlang4j.api.Erlang4jMessageLanguage.tuple;
import junit.framework.TestCase;

import com.ericsson.otp.erlang.OtpErlangPid;
import com.ericsson.otp.erlang.OtpNode;
import com.erlang4j.api.exceptionHandler.SysoutExceptionHandler;
import com.erlang4j.api.process.IProcess;
import com.erlang4j.internal.adapters.MockAdapter;
import com.erlang4j.internal.basicIo.IBasicMailBox;
import com.erlang4j.internal.basicIo.IBasicMailBoxFactory;
import com.erlang4j.internal.basicIo.MockBasicMailBox;
import com.erlang4j.internal.process.StateMachine;

public class Erlang4JTest extends TestCase {

	private MockBasicMailBox mockBasicMailBox;
	private OtpErlangPid self;
	private Erlang4J erlang4J;
	private SysoutExceptionHandler exceptionHandler;

	public void testExceptionhandler() {
		assertSame(exceptionHandler, erlang4J.exceptionHandler());
	}

	public void testReceive() {
		assertEquals(string("one"), erlang4J.receive());
		assertEquals(string("two"), erlang4J.receive());
	}

	public void testSendObject() {
		erlang4J.sendRaw("name1", "string1");
		assertEquals(string("string1"), mockBasicMailBox.sentObject);
		assertEquals("name1", mockBasicMailBox.serverName);
	}

	public void testSendPattern() {
		erlang4J.send("name1", "{Self,{a,P0}}", "param");
		assertEquals(tuple(self, tuple(atom("a"), string("param"))), mockBasicMailBox.sentObject);
		assertEquals("name1", mockBasicMailBox.serverName);
	}

	public void testSendBinding() {
		erlang4J.sendWithBinding("name1", "{Self,{a,Param1}}", binding("Param1", "param"));
		assertEquals(tuple(self, tuple(atom("a"), string("param"))), mockBasicMailBox.sentObject);
		assertEquals("name1", mockBasicMailBox.serverName);
	}

	public void testSpawn() {
		// not an integration test...the behaviour of the process is elsewhere
		IProcess spawnNoHandlers = erlang4J.spawn();
		assertTrue(spawnNoHandlers instanceof StateMachine);
		assertFalse(spawnNoHandlers.isAlive());

		IProcess spawnHandlers = erlang4J.spawn(new MockAdapter("One"), new MockAdapter("Two"), new MockAdapter("willCauseAWait"));
		assertTrue(spawnHandlers instanceof StateMachine);
		assertTrue(spawnHandlers.isAlive());
		spawnHandlers.terminate();
		assertFalse(spawnHandlers.isAlive());
	}

	@Override
	protected void setUp() throws Exception {
		super.setUp();
		self = new OtpNode("anyoldname").createPid();
		exceptionHandler = new SysoutExceptionHandler();
		erlang4J = new Erlang4J(new IBasicMailBoxFactory() {

			@Override
			public IBasicMailBox operations() {
				mockBasicMailBox = new MockBasicMailBox(self, makeArray("one", "two"));
				return mockBasicMailBox;
			}
		}, exceptionHandler);
	}
}
